//////////////////////////////////////////////////////////////////////////////////////////////////////
// 项目名   : Problem
// 文件名   : stack.h
// 作者     : Aiye
// 日期     : 2025/8/23 10:39
// 邮箱     : 2878548868@qq.com
// 摘要     : 线程安全栈和常规栈的实现
//////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef STACK_H
#define STACK_H
#include <deque>
#include <memory>
#include <stack>

/**
 * @brief 隔绝外部对栈的访问，避免直接使用 std::stack
 */
namespace MyStack
{
    /**
     * @brief 线程安全版本的栈
     */
    inline namespace SafetyThread
    {
        /**
         * @brief 重写空栈异常
         */
        struct empty_stack : std::exception
        {
            /**
             * @brief 空栈异常信息
             * @return 异常信息
             */
            const char* what() const noexcept override
            {
                return "empty stack";
            }
        };

        /**
         * @brief 包装 std::stack 的线程安全栈模板类
         * @tparam T 模板类型
         */
        template <class T>
        class ThreadSafeStack
        {
        public:
            /**
             * @brief 默认无参数构造函数
             */
            ThreadSafeStack() = default;

            /**
             * @brief 加锁保证复制的时候获取到的是一个稳定的状态
             * @param other 复制的栈对象
             */
            ThreadSafeStack(const ThreadSafeStack& other)
            {
                std::lock_guard guard(other._mutex); // 锁住其他对象的互斥锁
                _stack = other._stack;               // 复制栈内容
            }

            /**
             * @brief 禁用赋值操作符，避免多线程环境下的问题
             * @return
             */
            ThreadSafeStack& operator = (const ThreadSafeStack&) = delete;

            /**
             * @brief 将一个元素推入栈顶
             * @param value 模板值
             */
            void push(T value)
            {
                std::lock_guard guard(_mutex); // 锁住当前对象的互斥锁
                _stack.push(std::move(value));  // 推入元素
            }

            /**
             * @brief 通过智能指针弹出栈顶元素，确保异常安全
             * @return 获取栈顶元素的智能指针
             */
            std::shared_ptr<T> pop()
            {
                std::lock_guard guard(_mutex);
                if (_stack.empty())
                {
                    throw empty_stack(); // 抛出空栈异常
                }

                auto res = std::make_shared<T>(std::move(_stack.top()));
                _stack.pop();
                return res; // 返回栈顶元素的智能指针
            }

            /**
             * @brief 获取栈顶元素并弹出，通过引用传出
             * @param value 输入参数，弹出的栈顶元素通过引用传出
             */
            void pop(T& value)
            {
                std::lock_guard guard(_mutex);
                if (_stack.empty())
                {
                    throw empty_stack();
                }

                value = std::move(_stack.top());
                _stack.pop();
            }

            /**
             * @brief 获取栈的状态
             * @return 空栈状态
             */
            bool empty() const
            {
                std::lock_guard guard(_mutex);
                return _stack.empty();
            }

            ~ThreadSafeStack() = default;

        private:
            std::stack<T> _stack{};     ///> 栈容器
            mutable std::mutex _mutex;  ///> 互斥锁，允许常量方法加锁
        };
    }

    /**
     * @brief 常规版本的栈，不涉及线程安全
     */
    namespace RegularVersion
    {
        /**
         * @brief 自定义栈模板类，包装 std::deque 容器
         * @tparam T 模板类型
         * @tparam Container 容器类型，默认使用 std::deque，双端队列更适合栈的操作
         */
        template <class T, class Container = std::deque<T>>
        class stack
        {
        public:
            /**
         * @brief 用栈包装容器
         * @param refContainer deque 容器
         */
            explicit stack(const Container& refContainer)
                : _container(refContainer)
            {}

            /**
             * @brief 转移容器的所有权到栈
             * @param rrefContainer 右值引用的 deque 容器
             */
            explicit stack(Container&& rrefContainer = Container())
                : _container(std::move(rrefContainer))
            {}

        public:
            /**
         * @brief 栈是否为空
         * @return 是否为空
         */
            auto empty() const
            {
                return _container.empty();
            }

            /**
         * @brief 获取栈的容量大小
         * @return 栈的大小
         */
            auto size() const
            {
                return _container.size();
            }

            /**
         * @brief 获取栈顶元素的引用
         * @return 栈顶元素的引用
         */
            auto top() -> T&
            {
                return _container.back();
            }

            /**
         * @brief 获取栈顶元素的常量引用
         * @return 常量栈顶元素的引用
         */
            auto top() const -> const T&
            {
                return _container.back();
            }

            /**
         * @brief 推入一个元素到栈顶
         */
            void push(const T&)
            {
                _container.push_back(T());
            }

            /**
         * @brief 推进一个元素到栈顶
         */
            void push(T&&)
            {
                _container.push_back(std::move(T()));
            }

            /**
         * @brief 在栈顶添加一个元素
         * @tparam Args 模板参数包
         */
            template <class... Args>
            void emplace(Args&&...)
            {
                _container.emplace_back(std::forward<Args>(Args())...); // 完美转发参数
            }

            /**
         * @brief 弹出栈顶元素
         */
            void pop()
            {
                _container.pop_back();
            }

        protected:
            Container _container; ///> 存储容器
        };
    }
}

#endif //STACK_H
